package com.mystudy.leetcode.problem.heap.p_347;


import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
 * @program: infoalgorithm
 * @description: 前K个高频元素
 * @author: zhouzhilong
 * @create: 2019-08-06 16:43
 **/


/**
 * 给定一个非空的整数数组，返回其中出现频率前 k 高的元素。
 *
 * 示例 1:
 *
 * 输入: nums = [1,1,1,2,2,3], k = 2
 * 输出: [1,2]
 * 示例 2:
 *
 * 输入: nums = [1], k = 1
 * 输出: [1]
 * 说明：
 *
 * 你可以假设给定的 k 总是合理的，且 1 ≤ k ≤ 数组中不相同的元素的个数。
 * 你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。
 */
public class Solution {
    private static final Logger LOGGER = LoggerFactory.getLogger(Solution.class);

    long startTime = 0L;
    long endTime = 0L;


    @Before
    public void before() {
        startTime = System.nanoTime();
    }

    @Test
    public void test() {
        int [] arr = new int[]{4,1,-1,2,-1,2,3};
        List<Integer> integers = topKFrequent(arr, 2);
        LOGGER.debug("integers = [{}]",integers);
    }

    @After
    public void after() {
        endTime = System.nanoTime();
        double cost = (endTime - startTime) / 1000000.0;
        LOGGER.debug("cost = [{} ms ]",cost);
    }



    public List<Integer> topKFrequent(int[] nums, int k) {
        TreeMap<Integer, Integer> map = new TreeMap<>();
        for (int num : nums) {
            if (map.containsKey(num)) {
                map.put(num, map.get(num) + 1);
            } else {
                map.put(num, 1);
            }
        }
        PriorityQueue<Freq> pq = new PriorityQueue<>((Freq q1,Freq q2)->{
            if(q1.freq>q2.freq){
                return 1;
            }else{
                return 0;
            }
        });
        for (Integer key : map.keySet()) {
            if (pq.size() < k) {
                pq.offer(new Freq(key, map.get(key)));
            } else{
                Freq head = pq.peek();
                if (map.get(key) > head.freq) {
                    pq.poll();
                    pq.offer(new Freq(key, map.get(key)));
                }
            }
        }
        LinkedList<Integer> res = new LinkedList<>();
        while (!pq.isEmpty()) {
            res.add(pq.poll().e);
        }
        return res;
    }

    private class Freq implements Comparable<Freq> {
        int e;
        int freq;

        public Freq(int e, int freq) {
            this.e = e;
            this.freq = freq;
        }

        //频率最低的元素，优先度最高
        @Override
        public int compareTo(Freq o) {
            if (this.freq < o.freq) {
                return -1;
            } else if (this.freq > o.freq) {
                return 1;
            } else {
                return 0;
            }
        }
    }

}
